package com.googlecode.gwtbb.client.only.widget.form;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.googlecode.gwtbb.client.only.ClientOnlyMessages;
import com.googlecode.gwtbb.client.only.GwtbbCmess;
import com.googlecode.gwtbb.client.only.remote.ClientSession;
import com.googlecode.gwtbb.client.only.remote.NiceCallback;
import com.googlecode.gwtbb.client.only.widget.basic.*;
import com.googlecode.gwtbb.client.only.widget.form.entry.*;
import com.googlecode.gwtbb.client.shared.GwtbbSmess;
import com.googlecode.gwtbb.client.shared.SharedMessages;
import com.googlecode.gwtbb.client.shared.entity.user.User;
import com.googlecode.gwtbb.client.shared.remote.ClientResponse;
import com.googlecode.gwtbb.client.shared.remote.picture.PictureItemBean;
import com.googlecode.gwtbb.client.shared.validation.Failure;
import com.googlecode.gwtbb.client.shared.validation.FieldId;
import com.googlecode.gwtbb.client.shared.validation.Validateable;

import java.util.*;


/**
 * @author Abraham Grief
 * @version $Id$
 * @noinspection StringEquality
 * @since Feb 19, 2008
 */
public abstract class FormWidget extends Composite implements Validateable {
	protected static final ClientOnlyMessages cmss = GwtbbCmess.instance();
	protected static final SharedMessages smss = GwtbbSmess.instance();
	protected final AsyncCallback asyncCallback = new NiceCallback<ClientResponse>() {
		public void handle(ClientResponse clientResponse) {
			if (clientResponse.isSuccessful())
				handleSuccess(clientResponse);
			else
				displayFailures(clientResponse.getFailures());
		}
	};
	protected ClientSession session;
	private SimplePanel mainPanel;
	private VerticalPanel formPanel;
	private Widget loadingMsg;
	private Map<FieldId, FormEntry> fieldEntries;
	private boolean showSubmitButton = true;
	private Button cancelButton = new Button(GwtbbCmess.instance().cancel());
	private Map<Integer, FlexTable> tabForms;
	private CompleteProcessListenerCollection completeProcessListenerCollection = new CompleteProcessListenerCollection();
	private Widget mainForm;

	public FormWidget(ClientSession session) {
		this.session = session;
		mainPanel = new SimplePanel();
		initWidget(mainPanel);
		loadingMsg = new Label(cmss.loading());
		mainPanel.setWidget(loadingMsg);
		formPanel = new VerticalPanel();
		formPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		formPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
	}

	public Button getCancelButton() {
		return cancelButton;
	}

	public CompleteProcessListenerCollection getCompleteProcessListenerCollection() {
		return completeProcessListenerCollection;
	}

	public ClientSession getSession() {
		return session;
	}

	public void setSession(ClientSession session) {
		this.session = session;
	}

	public boolean isShowSubmitButton() {
		return showSubmitButton;
	}

	public void setShowSubmitButton(boolean showSubmitButton) {
		this.showSubmitButton = showSubmitButton;
	}

	public abstract List<FormEntry> getFormEntries();

	public abstract String getProcessName();

	public abstract String getProcessSuccess();

	public abstract String getProcessTitle();

	public void init() {
		formPanel.clear();
		List<FormEntry> formEntries = getFormEntries();
		int numFormEntries = formEntries.size();
		fieldEntries = new HashMap<FieldId, FormEntry>((numFormEntries + 1) * 10 * 7 + 1);
		EmptyFormEntry nullEntry = new EmptyFormEntry();
		fieldEntries.put(null, nullEntry);
		formPanel.add(nullEntry.getFailurePanel());

		tabForms = new HashMap<Integer, FlexTable>();
		for (int i = 0; i < numFormEntries; i++) {
			FormEntry formEntry = formEntries.get(i);
			fieldEntries.put(formEntry.getFieldId(), formEntry);
			if (formEntry.isDisplayedInitially())
				addFormEntry(formEntry);
		}

		initMainForm();

		ButtonBar buttonBar = new ButtonBar();
		buttonBar.setWidth("100%");
		buttonBar.add(cancelButton);
		formPanel.add(buttonBar);

		if (isShowSubmitButton()) {
			Button submitButton = new Button(getSubmitButtonText());
			buttonBar.add(submitButton);

			submitButton.addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					clearFailures();
					Map<FieldId, Failure> failures = validate(getNewFailuresMap(), 0);
					if (failures.isEmpty()) {
						doAction();
					} else {
						displayFailures(failures);
					}
				}
			});
		}

		mainPanel.setWidget(formPanel);
	}

	/**
	 * Returns the form to a state as if it was just created.
	 */
	public void reset() {
		for (FormEntry entry : fieldEntries.values()) {
			entry.clearFailures();
			entry.clearValue();
		}
		if (mainForm instanceof TabPanel)
			((TabPanel)mainForm).selectTab(0);
	}

	public void showForm() {
		mainPanel.setWidget(formPanel);
	}

	public void showLoadingMsg() {
		mainPanel.setWidget(loadingMsg);
	}

	protected void addFormEntry(FormEntry formEntry) {
		FlexTable formTable = getOrCreateFormTable(formEntry.getTabIndex());
		FlexTable.FlexCellFormatter formatter = formTable.getFlexCellFormatter();
		for (WidgetCell widgetCell : formEntry.getWidgetCells()) {
			int row = widgetCell.getRow();
			int col = widgetCell.getCol();
			formTable.setWidget(row, col, widgetCell.getWidget());
			formatter.setRowSpan(row, col, widgetCell.getRowSpan());
			formatter.setColSpan(row, col, widgetCell.getColSpan());
			formatter.setHorizontalAlignment(row, col, widgetCell.getHorizontalAlignment());
			formatter.setVerticalAlignment(row, col, widgetCell.getVerticalAlignment());
		}
	}

	protected FlexTable createFormTable() {
		FlexTable formTable = new FlexTable();
		formTable.setStylePrimaryName("gwtbb-formBody");
		formTable.setCellPadding(1);
		return formTable;
	}

	protected LabeledAsyncFileUploadFormEntry createLabeledAsyncFileUploadFormEntry(String field, int index, int row, int col, String fieldText, String formAction) {
		AsyncFileUpload asyncFileUpload = new AsyncFileUpload(formAction);
		final LabeledAsyncFileUploadFormEntry retVal = new LabeledAsyncFileUploadFormEntry(FieldId.create(field, index), fieldText, row, col, asyncFileUpload);
		asyncFileUpload.addAsyncFileUploadEventListener(new AsyncFileUploadListener() {
			public void onError(AsyncFileUploadErrorEvent event) {
				retVal.addFailure(new Failure(event.getErrorMessage()));
			}

			public void onValidateFileName(AsyncFileUploadValidateFileNameEvent event) {
			}

			public void onSubmit(FormSubmitEvent event) {
				retVal.clearFailures();
			}

			public void onSubmitComplete(FormSubmitCompleteEvent event) {
				retVal.clearFailures();
			}
		});
		return retVal;
	}

	protected LabeledCheckBoxFormEntry createLabeledCheckBoxFormEntry(String field, int index, boolean defaultValue, int row, int col, String fieldText) {
		return new LabeledCheckBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, new CheckBox());
	}

	protected HtmledCheckBoxFormEntry createHtmledCheckBoxFormEntry(String field, int index, boolean defaultValue, int row, int col, String fieldText) {
		return new HtmledCheckBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, new CheckBox());
	}

	protected LabeledCheckGroupFormEntry createLabeledCheckGroupFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText, List<String> values, List<String> labels) {
		int numCheckBoxes = values.size();
		List<CheckBox> checkBoxes = new ArrayList<CheckBox>(numCheckBoxes);
		for (int i = 0; i < numCheckBoxes; i++) {
			CheckBox cb = new CheckBox(labels.get(i));
			cb.setName(values.get(i));
			checkBoxes.add(cb);
		}
		return new LabeledCheckGroupFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, checkBoxes);
	}

	protected LabeledCompoundRadioGroupFormEntry createLabeledCompoundRadioGroupFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText, List<String> values, List<String> labels) {
		int numRadios = values.size();
		List<ValueRadioButton> vbrs = new ArrayList<ValueRadioButton>(numRadios);
		String groupName = getUniqueName(field, index);
		for (int i = 0; i < numRadios; i++) {
			vbrs.add(new ValueRadioButton(groupName, values.get(i), labels.get(i), true));
		}
		return new LabeledCompoundRadioGroupFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, vbrs);
	}

	protected LabeledLabelFormEntry createLabeledLabelFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText) {
		return new LabeledLabelFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, new Label());
	}

	protected LabeledMultiPictureFileUploadFormEntry createLabeledMultiPictureFileUploadFormEntry(String field, int index, int row, int col, String fieldText, String formAction, int maxNumPictures) {
		MultiPictureFileUpload multiPictureFileUpload = new MultiPictureFileUpload(formAction, maxNumPictures, new DialogCaptionFetcherFactory());
		final LabeledMultiPictureFileUploadFormEntry retVal = new LabeledMultiPictureFileUploadFormEntry(FieldId.create(field, index), fieldText, row, col, multiPictureFileUpload);
		multiPictureFileUpload.addAsyncFileUploadEventListener(new AsyncFileUploadListener() {
			public void onError(AsyncFileUploadErrorEvent event) {
				retVal.redisplayFailures();
			}

			public void onValidateFileName(AsyncFileUploadValidateFileNameEvent event) {
			}

			public void onSubmit(FormSubmitEvent event) {
				retVal.redisplayFailures();
			}

			public void onSubmitComplete(FormSubmitCompleteEvent event) {
				retVal.redisplayFailures();
			}
		});
		return retVal;
	}

	protected LabeledPasswordTextBoxFormEntry createLabeledPasswordTextBoxFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText) {
		return new LabeledPasswordTextBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, new PasswordTextBox());
	}

	protected LabeledRadioGroupFormEntry createLabeledRadioGroupFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText, List<String> values, List<String> labels) {
		int numRadios = values.size();
		List<ValueRadioButton> vbrs = new ArrayList<ValueRadioButton>(numRadios);
		String groupName = getUniqueName(field, index);
		for (int i = 0; i < numRadios; i++) {
			vbrs.add(new ValueRadioButton(groupName, values.get(i), labels.get(i), true));
		}
		return new LabeledRadioGroupFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, vbrs);
	}

	protected LabeledSuggestBoxFormEntry createLabeledSuggestBoxFormEntry(String field, int index, SuggestOracle suggestOracle, String defaultValue, int row, int col, String fieldText) {
		TextBox box = new TextBox();
		SuggestBox suggestBox = new SuggestBox(suggestOracle, box);
		suggestBox.addEventHandler(new SelectSuggestionHandler(box));
		return new LabeledSuggestBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, suggestBox);
	}

	protected LabeledTextAreaFormEntry createLabeledTextAreaFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText) {
		return new LabeledTextAreaFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, new TextArea());
	}

	protected LabeledTextBoxFormEntry createLabeledTextBoxFormEntry(String field, int index, String defaultValue, int row, int col, String fieldText) {
		return new LabeledTextBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, fieldText, new TextBox());
	}

	protected LabeledWidgetFormEntry createLabeledWidgetFormEntry(String field, int index, int row, int col, String fieldText, Widget widget) {
		return new LabeledWidgetFormEntry(FieldId.create(field, index), row, col, fieldText, widget);
	}

	protected SingleCheckBoxFormEntry createSingleCheckBoxFormEntry(String field, int index, boolean defaultValue, int row, int col) {
		return new SingleCheckBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, new CheckBox());
	}

	protected SingleLabelFormEntry createSingleLabelFormEntry(String field, int index, String defaultValue, int row, int col) {
		return new SingleLabelFormEntry(FieldId.create(field, index), defaultValue, row, col, new Label());
	}

	protected SingleMultiPictureFileUploadFormEntry createSingleMultiPictureFileUploadFormEntry(String field, int index, int row, int col, String formAction, int maxNumPictures) {
		MultiPictureFileUpload multiPictureFileUpload = new MultiPictureFileUpload(formAction, maxNumPictures, new DialogCaptionFetcherFactory());
		// todo implement default pics
		final SingleMultiPictureFileUploadFormEntry retVal = new SingleMultiPictureFileUploadFormEntry(FieldId.create(field, index), null, row, col, multiPictureFileUpload);
		multiPictureFileUpload.addAsyncFileUploadEventListener(new AsyncFileUploadListener() {
			public void onError(AsyncFileUploadErrorEvent event) {
				retVal.redisplayFailures();
			}

			public void onValidateFileName(AsyncFileUploadValidateFileNameEvent event) {
			}

			public void onSubmit(FormSubmitEvent event) {
				retVal.redisplayFailures();
			}

			public void onSubmitComplete(FormSubmitCompleteEvent event) {
				retVal.redisplayFailures();
			}
		});
		return retVal;
	}

	protected SingleTextAreaFormEntry createSingleTextAreaFormEntry(String field, int index, String defaultValue, int row, int col) {
		return new SingleTextAreaFormEntry(FieldId.create(field, index), defaultValue, row, col, new TextArea());
	}

	protected SingleTextBoxFormEntry createSingleTextBoxFormEntry(String field, int index, String defaultValue, int row, int col) {
		return new SingleTextBoxFormEntry(FieldId.create(field, index), defaultValue, row, col, new TextBox());
	}

	protected SingleWidgetFormEntry createSingleWidgetFormEntry(String field, int index, int row, int col, Widget widget) {
		return new SingleWidgetFormEntry(FieldId.create(field, index), row, col, widget);
	}

	protected abstract void doAction();

	protected void fromPictureItemBeans(String fieldName, int fieldIndex, List<PictureItemBean> pictureItemBeans) {
		MultiPictureFileUpload mpfu = (MultiPictureFileUpload)getFormEntry(fieldName, fieldIndex).getEntryWidget();
		List<PictureFileUpload> pictureFileUploads = mpfu.getPictureFileUploads();
		for (int i = 0; i < pictureItemBeans.size(); i++) {
			PictureItemBean pib = pictureItemBeans.get(i);
			PictureFileUpload pfu = pictureFileUploads.get(i);
			pfu.setCaption(pib.getCaption());
		}
	}

	protected boolean getBooleanValue(String field, int index) {
		return ((GetBooleanValue)getFormEntry(field, index)).getBooleanValue();
	}

	protected FormEntry getFormEntry(String field, int index) {
		return fieldEntries.get(FieldId.create(field, index));
	}

	protected Map<FieldId, Failure> getNewFailuresMap() {
		return new HashMap<FieldId, Failure>(8);
	}

	protected FlexTable getOrCreateFormTable(int tabIndex) {
		FlexTable formTable = tabForms.get(tabIndex);
		if (formTable == null) {
			tabForms.put(tabIndex, formTable = createFormTable());
		}
		return formTable;
	}

	protected String getSubmitButtonText() {
		return cmss.submit();
	}

	protected Widget getTabWidget(int i) {
		return new Label("Tab #" + i);
	}

	protected String getUniqueName(String field, int index) {
		return getProcessName() + field + index;
	}

	protected String getValue(String field, int index) {
		return getFormEntry(field, index).getValue();
	}

	protected final void handleSuccess(final ClientResponse success) {
		completeProcessListenerCollection.fireCompleteProcessEvent(new ProcessEvent() {
			public ClientResponse getClientResponse() {
				return success;
			}

			public FormWidget getFormWidget() {
				return FormWidget.this;
			}
		});
	}

	protected void initMainForm() {
		FlexTable tabForm = tabForms.get(0);
		if (tabForm != null) {
			TabPanel tabs = new TabPanel();
			int i = 0;
			do {
				tabs.add(tabForm, getTabWidget(i));
				tabForm = tabForms.get(++i);
			} while (tabForm != null);
			tabs.selectTab(0);
			mainForm = tabs;
		} else {
			mainForm = tabForms.get(FormEntry.NO_TABS);
		}
		formPanel.add(mainForm);
	}

	protected void removeFormEntry(FormEntry formEntry) {
		FlexTable formTable = getOrCreateFormTable(formEntry.getTabIndex());
		for (WidgetCell widgetCell : formEntry.getWidgetCells())
			formTable.remove(widgetCell.getWidget());
	}

	protected void setValue(String field, int index, String value) {
		getFormEntry(field, index).setValue(value);
	}

	/*
	private void squeezeFormEntry(FormEntry formEntry) {
/*
		SortedMap<WidgetCell, Integer> rowOffsets = new TreeMap<WidgetCell, Integer>(WidgetCell.BOTTOM_UP);
		List<WidgetCell> newCells = formEntry.getWidgetCells();
		for (WidgetCell newCell : newCells) {
			for (FormEntry oldFormEntry : fieldEntries.values()) {
				for (WidgetCell oldWidgetCell : oldFormEntry.getWidgetCells()) {
					if (oldWidgetCell.getRow() >= newCell.getRow()) {
						int oldMinCol = oldWidgetCell.getCol();
						int oldMaxCol = oldMinCol + oldWidgetCell.getColSpan();
						int newMinCol = newCell.getCol();
						int newMaxCol = newMinCol + newCell.getColSpan();
						// if it's under the same column
						if ((oldMinCol >= newMinCol && oldMinCol <= newMaxCol)
							|| (oldMaxCol >= newMinCol && oldMaxCol <= newMaxCol)
							|| (oldMinCol <= newMinCol && oldMaxCol >= newMaxCol)) {
							int rowOffset = newCell.getRowSpan();
							Integer prevRowOffset = rowOffsets.get(oldWidgetCell);
							if (prevRowOffset != null)
								rowOffset += prevRowOffset;
							rowOffsets.put(oldWidgetCell, rowOffset);
						}
					}
				}
			}
		}
		for (Map.Entry<WidgetCell, Integer> widgetCellRowOffset : rowOffsets.entrySet()) {

		}
*/
	/*
	   List<WidgetCell> newWidgetCells = ObjectUtils0.copyAndSort(formEntry.getWidgetCells(), WidgetCell.TOP_DOWN);

	   // this should also work even if there are multiple new widgetCells on top of each other
	   // because cells are inserted in top-down order
	   for (WidgetCell newWidgetCell : newWidgetCells) {
		   for (int row = formTable.getRowCount() - 1; row >= newWidgetCell.getRow(); row--) {
			   for (int colOffset = 0; colOffset < newWidgetCell.getColSpan(); colOffset++) {
				   int col = newWidgetCell.getCol() + colOffset;
				   Widget widget = formTable.getWidget(row, col);
				   // this won't work properly for widgets that span multiple rows and cols
				   // not sure how to fix it until i found out if getWidget returns the same widget
				   // multiple times for widgets that span multiple cells, or if it only returns the
				   // widget for the upper left cell
				   if (widget != null) {
					   int newRow = row + newWidgetCell.getRowSpan();
					   formTable.remove(widget);
					   FlexTable.FlexCellFormatter formatter = formTable.getFlexCellFormatter();
					   formTable.setWidget(newRow, col, widget);
					   formatter.setRowSpan(newRow, col, formatter.getRowSpan(row, col));
					   formatter.setColSpan(newRow, col, formatter.getColSpan(row, col));
					   formatter.setHorizontalAlignment(row, col, GwtUtils.getHorizontalAlignment(formatter, row, col));
					   formatter.setVerticalAlignment(row, col, GwtUtils.getVerticalAlignment(formatter, row, col));
				   }
			   }
		   }
	   }
	   addFormEntry(formEntry);
	   */
//	}

	protected List<PictureItemBean> toPictureItemBeans(Map<FieldId, Failure> failures, String fieldName, int fieldIndex) {
		MultiPictureFileUpload mpfu = (MultiPictureFileUpload)getFormEntry(fieldName, fieldIndex).getEntryWidget();
		List<PictureFileUpload> pictureFileUploads = mpfu.getPictureFileUploads();
		List<PictureItemBean> pictureItems = new ArrayList<PictureItemBean>(pictureFileUploads.size());
		for (PictureFileUpload pfu : pictureFileUploads) {
			String filename = null;
			String caption = null;
			if (pfu.isUploading())
				failures.put(FieldId.create(fieldName, fieldIndex), new Failure(cmss.uploadInProgress()));
			else if (pfu.isUploaded()) {
				filename = pfu.getServerFileName();
				caption = pfu.getCaption();
			}
			pictureItems.add(new PictureItemBean(filename, caption));
		}
		return pictureItems;
	}

	/*
	private void unsqueezeFormEntry(FormEntry formEntry) {
		/*
		List<WidgetCell> badWidgetCells = ObjectUtils0.copyAndSort(formEntry.getWidgetCells(), WidgetCell.BOTTOM_UP);
		for (WidgetCell badWidgetCell : badWidgetCells) {
			for (int row = badWidgetCell.getRow() + badWidgetCell.getRowSpan(); row < formTable.getRowCount(); row++) {
				for (int colOffset = 0; colOffset < badWidgetCell.getColSpan(); colOffset++) {
					int col = badWidgetCell.getCol() + colOffset;
					Widget widget = formTable.getWidget(row, col);
					// see comments for squeezeFormEntry
					// also, we may have to remove or clear styles from bottom row of table
					if (widget != null) {
						int newRow = row - badWidgetCell.getRowSpan();
						FlexTable.FlexCellFormatter formatter = formTable.getFlexCellFormatter();
						formTable.setWidget(newRow, col, widget);
						formatter.setRowSpan(newRow, col, formatter.getRowSpan(row, col));
						formatter.setColSpan(newRow, col, formatter.getColSpan(row, col));
						formatter.setHorizontalAlignment(row, col, GwtUtils.getHorizontalAlignment(formatter, row, col));
						formatter.setVerticalAlignment(row, col, GwtUtils.getVerticalAlignment(formatter, row, col));
					}
				}
			}
		}
		*/
//	}

	protected void validatePrivilege(Map<FieldId, Failure> failures, User.PrivilegeLevel privilegeLevel) {
		if (session.isLoggedOut())
			failures.put(null, new Failure(smss.loggedOut()));
		else {
			User user = session.getUser();
			if (user.getPrivilegeLevel().ordinal() < privilegeLevel.ordinal())
				failures.put(null, new Failure(smss.insufficientPrivileges()));
		}
	}

	private void clearFailures() {
		for (FormEntry formEntry : fieldEntries.values())
			formEntry.clearFailures();
	}

	private void displayFailures(Map<FieldId, Failure> failures) {
		for (Map.Entry<FieldId, Failure> mapEntry : failures.entrySet()) {
			FieldId fieldId = mapEntry.getKey();
			Failure failure = mapEntry.getValue();
			FormEntry entry = fieldEntries.get(fieldId);
			if (entry == null)
				entry = fieldEntries.get(null);
			entry.addFailure(failure);
		}
	}

	public class DialogCaptionFetcherFactory implements CaptionFetcherFactory {
		public CaptionFetcher constructCaptionFetcher() {
			return new DialogCaptionFetcher();
		}
	}

	public class DialogCaptionFetcher implements CaptionFetcher {
		// todo consolidate with FormDialog without making cycle
		// todo don't recreate form and dialog each fetch
		public void fetchCaption(String caption, final AsyncCallback<String> whenFetched) {
			final DialogBox captionDialog = new DialogBox();
			final CaptionForm captionForm = new CaptionForm(session);
			captionDialog.setWidget(captionForm);
			captionForm.setCaption(caption);
			captionForm.getCancelButton().addClickListener(new ClickListener() {
				public void onClick(Widget sender) {
					captionDialog.hide();
				}
			});
			captionForm.getCompleteProcessListenerCollection().addCompleteProcessListener(new CompleteProcessListener() {
				public void onProcessCompletion(ProcessEvent processEvent) {
					whenFetched.onSuccess(captionForm.getCaption());
					captionDialog.hide();
				}
			});
			captionDialog.setText(captionForm.getProcessTitle());
			captionDialog.center();
		}
	}
}